/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
/**
 * Software License, Version 1.0
 * 
 * Copyright 2004 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.gridapps.nbgridftp.publisher;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Properties;

import javax.jms.JMSException;

/**
 * This class is a "data channel" of GridFTP. In this class we will store 
 * actual data from client in to the local temporary file and then it will
 * read data from local temporary file and send to the other end of data
 * channel by using NaradaBrokering.
 * 
 * Current version of GridFTP with NaradaBrokering makes GridFTP server 
 * connect to the GridFTP client. This means we are only using as GridFTP with
 * following settings: client.setLocalPassive(); client.setActive();.
 **/
public class Client2NBData extends Thread {

    private static Socket s;
    private static InputStream fromClient;
    private static OutputStream toClient;

    private String clientName;

    private final String CLOSE = "CLOSE: ";
    private final String AUTH  = "AUTH: ";
    private final String DATA  = "DATA: ";
    private final String SET  = "SET: ";

    private String host;
    private int port;

    private boolean closeOutput = false;
    private boolean finished = true;

    private File f;
    private String tempFile = "temp" + File.separator;
    private String tempDir = "temp" + File.separator;

    private Client2NBControl control;
    
    public Client2NBData(Client2NBControl control, String tempFile) {

        this.control = control;

        if (tempFile.endsWith("/") | tempFile.endsWith("\\")) {
            this.tempFile = tempFile;
            this.tempDir = tempFile;
        } else{
            this.tempFile = tempFile + File.separator;
            this.tempDir = tempFile + File.separator;
        }
    }

    /**
     * Setting the host name and port number of oped client data channel.
     **/
    public void setHostPort(String host, int port){

        this.host = host;
        this.port = port;
    }

    public void setFileName(String fileName) {

        tempFile += fileName.replace('/','%');
    }

    public String getFileName(){

        return tempFile;
    }
    /**
     * Check for data tranferring is finished or not.
     *
     * return: It will return false only during transfering data from
     *         local temporary file to NaradaBrokering. Otherwise it will 
     *         retun true.
     **/
    public synchronized boolean isFinished() {

        return finished;
    }

    public void run() {

        try {
            s = new Socket(host,port); 
            
            fromClient = s.getInputStream();
            toClient   = s.getOutputStream();
            
            clientName = s.getInetAddress().getHostAddress() + ":" + 
                s.getPort();
            
        } catch (Exception e) {
            System.err.println("client data::run:"+e);
            setFinished(true);
            control.dataClosed();
        }            


        byte[] request = new byte[2048];

        while(true){

            int bytes_read = 0;
            try {
                bytes_read = fromClient.read(request);
            } catch (IOException e) {
                dataClosed(true);
                break;
            }

            if ((bytes_read > 0) && new String(request, 0, bytes_read).
                startsWith("Ready for NB.")) {
                
                // looking for temporary diractory to store file. If this
                // diractory is not present, create one.
                
                new File(tempDir).mkdir();
                f = new File(tempFile);

                try {
                    FileOutputStream out = new FileOutputStream(tempFile);
                    while ((bytes_read = fromClient.read(request)) != -1)
                        out.write(request, 0, bytes_read);

                    out.close();
                } catch (FileNotFoundException e) {
                    break;
                } catch (IOException e) {
                    dataClosed(true);
                    break;
                }

                setFinished(false);
                
                try {
                    Properties fragmentationProperties =  new Properties();
                    fragmentationProperties.put("fragmentSize", "400000");
                    fragmentationProperties.put("fileLocation", tempFile);
                    control.publishEvent("[Send File]",
                                                  fragmentationProperties);
                    closeOutput = true;
                } catch (cgl.narada.service.ServiceException e) {

                    dataClosed(true);
                    break;
                } 
                setFinished(true);

                break;
            } else {
                try {
                    control.writeMessage(request, bytes_read, AUTH);
                } catch (JMSException e) {

                    dataClosed(true);
                }
            }
        }
    } 
    
    public void write2Client(byte[] message, int length) {

        try {
            toClient.write(message, 0, length);
            toClient.flush();
        } catch (IOException e) {

            close();
        }
    }

    public void delete() {
        
        if (f != null) f.delete();
    }

    public static void close() {

        try {
            if (toClient != null) toClient.close();
            if (fromClient != null) fromClient.close();
            if (s != null)  s.close();
            
        } catch (IOException e){
        } 
    }

    private synchronized void setFinished(boolean finished) {

        this.finished = finished;
    }

    private void dataClosed(boolean bool) {

        setFinished(bool);
        control.dataClosed();
    }
}
